package services

import (
	"gitee.com/kun_liu/to-log/app/models"
	"gitee.com/kun_liu/to-log/pkg/database"
	"gorm.io/gorm"
)

// PostService 文章服务
type PostService struct {
	db *gorm.DB
}

// NewPostService 创建文章服务
func NewPostService() *PostService {
	return &PostService{
		db: database.GetDB(),
	}
}

// GetPosts 获取文章列表
func (s *PostService) GetPosts(page, pageSize int) ([]models.Post, int64, error) {
	var posts []models.Post
	var total int64

	// 获取总数
	s.db.Model(&models.Post{}).Where("type = ?", "post").Count(&total)

	// 获取分页数据
	result := s.db.Where("type = ?", "post").Order("created DESC").Limit(pageSize).Offset((page - 1) * pageSize).Find(&posts)

	// 加载关联数据
	for i := range posts {
		s.db.Model(&posts[i]).Association("Categories").Find(&posts[i].Categories)
		s.db.Model(&posts[i]).Association("Tags").Find(&posts[i].Tags)
		s.db.Model(&posts[i]).Association("User").Find(&posts[i].User)
	}

	return posts, total, result.Error
}

// GetPostBySlug 根据别名获取文章
func (s *PostService) GetPostBySlug(slug string) (models.Post, error) {
	var post models.Post
	result := s.db.Where("slug = ? AND type = ?", slug, "post").First(&post)
	if result.Error != nil {
		return post, result.Error
	}

	// 加载关联数据
	s.db.Model(&post).Association("Categories").Find(&post.Categories)
	s.db.Model(&post).Association("Tags").Find(&post.Tags)

	// 增加阅读次数
	s.db.Model(&post).UpdateColumn("views", gorm.Expr("views + ?", 1))

	return post, nil
}

// GetPostByID 根据ID获取文章
func (s *PostService) GetPostByID(id uint) (models.Post, error) {
	var post models.Post
	result := s.db.First(&post, id)
	if result.Error != nil {
		return post, result.Error
	}

	// 加载关联数据
	s.db.Model(&post).Association("Categories").Find(&post.Categories)
	s.db.Model(&post).Association("Tags").Find(&post.Tags)

	return post, nil
}

// CreatePost 创建文章
func (s *PostService) CreatePost(post *models.Post) error {
	// 开始事务
	tx := s.db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 创建文章
	if err := tx.Create(post).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 添加分类关联
	if len(post.Categories) > 0 {
		if err := tx.Model(post).Association("Categories").Replace(post.Categories); err != nil {
			tx.Rollback()
			return err
		}
	}

	// 提交事务
	return tx.Commit().Error
}

// UpdatePost 更新文章
func (s *PostService) UpdatePost(post *models.Post) error {
	// 开始事务
	tx := s.db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 更新文章
	if err := tx.Save(post).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 更新分类关联
	if len(post.Categories) > 0 {
		if err := tx.Model(post).Association("Categories").Replace(post.Categories); err != nil {
			tx.Rollback()
			return err
		}
	} else {
		if err := tx.Model(post).Association("Categories").Clear(); err != nil {
			tx.Rollback()
			return err
		}
	}

	// 提交事务
	return tx.Commit().Error
}

// DeletePost 删除文章
func (s *PostService) DeletePost(id uint) error {
	// 开始事务
	tx := s.db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 获取文章
	var post models.Post
	if err := tx.First(&post, id).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 清除关联
	if err := tx.Model(&post).Association("Categories").Clear(); err != nil {
		tx.Rollback()
		return err
	}
	if err := tx.Model(&post).Association("Tags").Clear(); err != nil {
		tx.Rollback()
		return err
	}

	// 删除文章
	if err := tx.Delete(&post).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 提交事务
	return tx.Commit().Error
}

// GetPostsByCategory 获取分类下的文章
func (s *PostService) GetPostsByCategory(categoryID uint, page, pageSize int) ([]models.Post, int64, error) {
	var posts []models.Post
	var total int64

	// 获取总数
	s.db.Model(&models.Post{}).Joins("JOIN relationships ON relationships.cid = posts.cid").Where("relationships.mid = ? AND posts.type = ?", categoryID, "post").Count(&total)

	// 获取分页数据
	result := s.db.Joins("JOIN relationships ON relationships.cid = posts.cid").Where("relationships.mid = ? AND posts.type = ?", categoryID, "post").Order("posts.created DESC").Limit(pageSize).Offset((page - 1) * pageSize).Find(&posts)

	return posts, total, result.Error
}

// GetPostsByTag 获取标签下的文章
func (s *PostService) GetPostsByTag(tagID uint, page, pageSize int) ([]models.Post, int64, error) {
	var posts []models.Post
	var total int64

	// 获取总数
	s.db.Model(&models.Post{}).Joins("JOIN relationships ON relationships.cid = posts.cid").Where("relationships.mid = ? AND posts.type = ?", tagID, "post").Count(&total)

	// 获取分页数据
	result := s.db.Joins("JOIN relationships ON relationships.cid = posts.cid").Where("relationships.mid = ? AND posts.type = ?", tagID, "post").Order("posts.created DESC").Limit(pageSize).Offset((page - 1) * pageSize).Find(&posts)

	return posts, total, result.Error
}
